import java.awt.Point;
import java.util.Random;

import jason.environment.grid.GridWorldModel;
import jason.environment.grid.Location;

public class Model extends GridWorldModel {
	public static final int Gsize = 20 ;
	public static final int GARB = 16;
	public static final int OBSTACLE =4	;
	
	public static final int MErr = 2; // max error in pick garb
	int nerr; // number of tries of pick garb
	boolean r1HasGarb = false; // whether r1 is carrying garbage or not

	Random random = new Random(System.currentTimeMillis());

	public  Model() {
		super(Gsize, Gsize, 2);

		// initial location of agents
		try {
			
			setAgPos(0, 0, 0);
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		// initial location of obstacle
		add(OBSTACLE, 2, 3);
		add(OBSTACLE, 2, 4);
		add(OBSTACLE, 2, 5);
		add(OBSTACLE, 2, 6);
		add(OBSTACLE, 2, 7);

		add(OBSTACLE, 2, 12);
		add(OBSTACLE, 2, 13);
		add(OBSTACLE, 2, 14);
		add(OBSTACLE, 2, 15);
		add(OBSTACLE, 2, 16);
	

		add(OBSTACLE, 14, 2);
		add(OBSTACLE, 15, 2);
		add(OBSTACLE, 16, 2);
		add(OBSTACLE, 17, 2);
		add(OBSTACLE, 17, 3);
		add(OBSTACLE, 17, 4);
		add(OBSTACLE, 17, 5);
		add(OBSTACLE, 17, 6);
		add(OBSTACLE, 17, 7);

		add(OBSTACLE, 17, 12);
		add(OBSTACLE, 17, 13);
		add(OBSTACLE, 17, 14);
		add(OBSTACLE, 17, 15);
		add(OBSTACLE, 17, 16);
		add(OBSTACLE, 16, 17);

		add(OBSTACLE, 8, 4);
		add(OBSTACLE, 9, 4);
		add(OBSTACLE, 10, 4);
		add(OBSTACLE, 11, 4);

		add(OBSTACLE, 7, 8);
		add(OBSTACLE, 7, 9);
		add(OBSTACLE, 7, 10);
		add(OBSTACLE, 7, 11);

		add(OBSTACLE, 8, 15);
		add(OBSTACLE, 9, 15);
		add(OBSTACLE, 10, 15);
		add(OBSTACLE, 11, 15);

		add(OBSTACLE, 12, 8);
		add(OBSTACLE, 12, 9);
		add(OBSTACLE, 12, 10);
		add(OBSTACLE, 12, 11);

		// initial location of garbage
		add(GARB, 2, 0);
		add(GARB, 3, 0);
		add(GARB, 6, 0);
		add(GARB, 7, 0);
		add(GARB, 9, 1);
		add(GARB, 7, 3);
		add(GARB, 1, 5);
		add(GARB, 4, 5);
		add(GARB, 6, 5);
		add(GARB, 13, 5);
		add(GARB, 19, 5);
		add(GARB, 15, 7);
		add(GARB, 4, 8);
		add(GARB, 10, 8);
		add(GARB, 0, 9);
		add(GARB, 3, 9);
		add(GARB, 14, 9);
		add(GARB, 17, 9);
		add(GARB, 19, 9);
		add(GARB, 1, 10);
		add(GARB, 19, 13);
		add(GARB, 1, 14);
		add(GARB, 3, 15);

	}

	public boolean checkPath(int x, int y) throws Exception {
		Location r1 = getAgPos(0);
		if (r1.x < x) {
			r1.x++;
			if (this.hasObject(OBSTACLE, r1))
				return false;
		} else if (r1.x > x) {
			r1.x--;
			if (this.hasObject(OBSTACLE, r1))
				return false;
		}
		if (r1.y < y) {
			r1.y++;
			if (this.hasObject(OBSTACLE, r1))
				return false;
		} else if (r1.y > y) {
			r1.y--;
			if (this.hasObject(OBSTACLE, r1))
				return false;
		}
		return true;
	}
	void moveTowards(int x, int y) throws Exception {
		if (checkPath(x, y)) {
			Location r1 = getAgPos(0);
			if (r1.x < x)
				r1.x++;
			else if (r1.x > x)
				r1.x--;
			if (r1.y < y)
				r1.y++;
			else if (r1.y > y)
				r1.y--;
			setAgPos(0, r1);
			//setAgPos(1, getAgPos(1)); // just to draw it in the view
		} else { // find a entrepot
			Location r1 = getAgPos(0);
			Point entrepot = new Point(0, 0); // lay diem trung gian tranh chuong ngai
			double minDis = 100;  
			for (int i = 0; i < this.getWidth(); i++)
				for (int j = 0; j < this.getHeight(); j++)
					if (!this.hasObject(OBSTACLE, i, j)
							&& checkPath(i, j)
							&& ((getDistance(r1.x, r1.y, i, j) + getDistance(
									r1.x, r1.y, x, y)) < minDis)) {
						minDis = getDistance(r1.x, r1.y, i, j)
								+ getDistance(r1.x, r1.y, x, y);
						entrepot = new Point(i, j);
						System.out.println(entrepot.toString());
					}// end of if
			try {
			
		//Thread.sleep(2000); // toc do xu ly hien thi nhanh or cham
				this.moveTowards(entrepot.x  , entrepot.y - 1);
			} catch (Exception e) {
				Random ra = new Random();  // chon diem ngau nhien neu ko tim duoc diem trung gian
				int randomPosition = ra.nextInt(getAgPos(0).x);
				while (!this.hasObject(OBSTACLE, randomPosition , randomPosition)) {
					randomPosition = ra.nextInt((getAgPos(0).x + getAgPos(0).y)  );
					this.moveTowards(randomPosition  , randomPosition);
				}
											
			}
			// model.moveTowards(x, y); 
		}

	}

	void burnGarb() {
		// r2 location has garbage
		if (this.hasObject(GARB, getAgPos(0))) {
			remove(GARB, getAgPos(0));
		}
	}

	public double getDistance(int x1, int y1, int x2, int y2) {

		// double d= 0;
		return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
	}
}
